/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.moedik.controller;

import com.moedik.classes.City;
import com.moedik.classes.Role;
import com.moedik.classes.User;
import com.moedik.model.CityModel;
import com.moedik.model.RoleModel;
import com.moedik.model.UserModel;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author SAMMY
 */
public class UserController extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, NoSuchAlgorithmException, SQLException {
        response.setContentType("text/html;charset=UTF-8");
        
        if (request.getParameter("action").equals("login")) {
            if (request.getMethod().equals("POST")) {
                String username = request.getParameter("username");
                String password = request.getParameter("password");
                
                UserModel userModel = new UserModel();
                int userId = userModel.validate(username, password);
                
                if (userId > 0) {
                    User user = userModel.get(userId);
                    
                    request.getSession().setAttribute("authenticated", true);
                    request.getSession().setAttribute("user", user);
                    request.setAttribute("title", "Home");
                    request.getRequestDispatcher("home.jsp").forward(request, response);
                } else {
                    request.getSession().setAttribute("flash", "Login failed.");
                    request.setAttribute("title", "Login");
                    request.getRequestDispatcher("users/login.jsp").forward(request, response);
                }
            } else {
                request.setAttribute("title", "Login");
                request.getRequestDispatcher("users/login.jsp").forward(request, response);
            }
            
            request.setAttribute("title", "Login");
        } else if (request.getParameter("action").equals("logout")) {
            request.getSession().setAttribute("authenticated", false);
            request.getSession().removeAttribute("user");
            request.getSession().setAttribute("flash", "You have been logged out.");
            request.setAttribute("title", "Login");
            request.getRequestDispatcher("users/login.jsp").forward(request, response);
        } else if (request.getParameter("action").equals("edit")) {
            int userId = 0;
            
            if (((User) request.getSession().getAttribute("user")).getRoleId() == 1) {
                userId = Integer.parseInt(request.getParameter("id"));
            } else {
                userId = ((User) request.getSession().getAttribute("user")).getId();
            }
            
            if (request.getMethod().equals("POST")) {
                String name = request.getParameter("name");
                String password = request.getParameter("password");
                String email = request.getParameter("email");
                String address = request.getParameter("address");
                int cityId = Integer.parseInt(request.getParameter("city"));
                String phone = request.getParameter("phone");
                
                int roleId;
                
                if (((User) request.getSession().getAttribute("user")).getRoleId() == 1) {
                    roleId = Integer.parseInt(request.getParameter("role"));
                } else {
                    roleId = ((User) request.getSession().getAttribute("user")).getRoleId();
                }
                
                if(!password.equals("")){
                    MessageDigest md = MessageDigest.getInstance("MD5");
                    byte[] md5hash = new byte[32];
                    md.update(password.getBytes("iso-8859-1"), 0, password.length());
                    md5hash = md.digest();
                    StringBuffer buf = new StringBuffer();

                    for (int i = 0; i < md5hash.length; i++) {
                        int halfbyte = (md5hash[i] >>> 4) & 0x0F;
                        int two_halfs = 0;
                        do {
                            if ((0 <= halfbyte) && (halfbyte <= 9)) {
                                buf.append((char) ('0' + halfbyte));
                            } else {
                                buf.append((char) ('a' + (halfbyte - 10)));
                            }
                            halfbyte = md5hash[i] & 0x0F;
                        } while (two_halfs++ < 1);
                    }
                    password = buf.toString();
                }
                
                UserModel userModel = new UserModel();
                userModel.update(userId, name, password, roleId, email, address, cityId, phone);
                
                
                User user = userModel.get(userId);
                
                
                CityModel cityModel = new CityModel();
                ArrayList<City> cities = new ArrayList<City>();
                cities = cityModel.getAll();
                
                request.getSession().setAttribute("flash", "Profil Anda telah tersimpan.");
                
                if (((User) request.getSession().getAttribute("user")).getRoleId() == 1) {
                    response.sendRedirect("./users?action=manage");
                } else {
                    request.setAttribute("user", user);
                    request.setAttribute("cities", cities);
                    request.setAttribute("title", "Home");
                    request.getRequestDispatcher("home.jsp").forward(request, response);
                }
            } else {
                UserModel userModel = new UserModel();
                User user = userModel.get(userId);
                
                CityModel cityModel = new CityModel();
                ArrayList<City> cities = new ArrayList<City>();
                cities = cityModel.getAll();
                
                RoleModel roleModel = new RoleModel();
                ArrayList<Role> roles = roleModel.getAll();
                
                request.setAttribute("user", user);
                request.setAttribute("roles", roles);
                request.setAttribute("cities", cities);
                request.setAttribute("title", "Edit Profile");
                request.getRequestDispatcher("users/edit.jsp").forward(request, response);
            }
        } else if (request.getParameter("action").equals("signup")) {
            CityModel cityModel = new CityModel();
            ArrayList<City> cities = new ArrayList<City>();
            cities = cityModel.getAll();
            
            if (request.getMethod().equals("POST")) {       //ada masukan pengguna
                UserModel userModel = new UserModel();
                
                String name = request.getParameter("name");
                String username = request.getParameter("username");
                
                int isUsernameValid = userModel.validateUsername(username);
                
                if (isUsernameValid == 0) {     //cek apakah username sudah pernah dipakai sebelumnya
                    String email = request.getParameter("email");
                    int isEmailValid = userModel.validateEmail(email);
                    if (isEmailValid == 0) {     //cek apakah email sudah pernah dipakai sebelumnya
                        String phone = request.getParameter("phone");
                        int isPhoneValid = userModel.validatePhone(phone);
                        if (isPhoneValid == 0) {     //cek apakah phone sudah pernah dipakai sebelumnya
                            //compute md5 hash of password
                            String password = request.getParameter("password");
                            MessageDigest md = MessageDigest.getInstance("MD5");
                            byte[] md5hash = new byte[32];
                            md.update(password.getBytes("iso-8859-1"), 0, password.length());
                            md5hash = md.digest();
                            StringBuffer buf = new StringBuffer();
                            for (int i = 0; i < md5hash.length; i++) {
                                int halfbyte = (md5hash[i] >>> 4) & 0x0F;
                                int two_halfs = 0;
                                do {
                                    if ((0 <= halfbyte) && (halfbyte <= 9)) {
                                        buf.append((char) ('0' + halfbyte));
                                    } else {
                                        buf.append((char) ('a' + (halfbyte - 10)));
                                    }
                                    halfbyte = md5hash[i] & 0x0F;
                                } while (two_halfs++ < 1);
                            }
                            password = buf.toString();
                            //end of computing md5 hash of password

                            String address = request.getParameter("address");
                            
                            String city = request.getParameter("city");
                            int city_id = Integer.parseInt(city);
                            
                            int signup_id = userModel.signup(username, password, 4, name, email, address, city_id, phone);
                            if (signup_id > 0) {        //register berhasil, redirect ke halaman login
                                request.getSession().setAttribute("flash", "Terima kasih telah melakukan registrasi. Silakan lakukan login untuk dapat menikmati layanan yang tersedia.");
                                request.setAttribute("title", "Login");
                                request.getRequestDispatcher("users/login.jsp").forward(request, response);
                            } else {        //sign up gagal
                                request.getSession().setAttribute("flash", "Terjadi masalah dalam proses pengiriman data. Silakan ulangi registrasi.");
                                request.setAttribute("cities", cities);
                                request.setAttribute("title", "Sign Up");
                                request.getRequestDispatcher("users/signup.jsp").forward(request, response);
                            }
                        } else {        //phone tidak valid (sudah ada di database)
                            request.getSession().setAttribute("flash", "Nomor telepon yang Anda masukkan sudah pernah terdaftar. Silakan lakukan registrasi ulang dengan nomor telepon lain.");
                            request.setAttribute("cities", cities);
                            request.setAttribute("title", "Sign Up");
                            request.getRequestDispatcher("users/signup.jsp").forward(request, response);
                        }
                    } else {        //email tidak valid (sudah ada di database)
                        request.getSession().setAttribute("flash", "Email yang Anda masukkan sudah pernah terdaftar. Silakan lakukan registrasi ulang dengan email lain.");
                        request.setAttribute("cities", cities);
                        request.setAttribute("title", "Sign Up");
                        request.getRequestDispatcher("users/signup.jsp").forward(request, response);
                    }
                } else {        //username tidak valid (sudah ada di database)
                    request.getSession().setAttribute("flash", "Username yang Anda masukkan tidak valid karena sudah dipakai oleh user lain. Silakan lakukan registrasi ulang dengan username lain.");
                    request.setAttribute("cities", cities);
                    request.setAttribute("title", "Sign Up");
                    request.getRequestDispatcher("users/signup.jsp").forward(request, response);
                }
            } else {        //tidak ada masukan pengguna
                request.setAttribute("cities", cities);
                request.setAttribute("title", "Sign Up");
                request.getRequestDispatcher("users/signup.jsp").forward(request, response);
            }
        } else if (request.getParameter("action").equals("add")) {
            
            CityModel cityModel = new CityModel();
            ArrayList<City> cities = new ArrayList<City>();
            cities = cityModel.getAll();
                
            RoleModel roleModel = new RoleModel();
            ArrayList<Role> roles = roleModel.getAll();
                        
            
            if (request.getMethod().equals("POST")) {       //ada masukan pengguna
                UserModel userModel = new UserModel();
                request.setAttribute("roles", roles);
                
                String name = request.getParameter("name");
                String username = request.getParameter("username");
                
                int isUsernameValid = userModel.validateUsername(username);
                
                if (isUsernameValid == 0) {     //cek apakah username sudah pernah dipakai sebelumnya
                    String email = request.getParameter("email");
                    int isEmailValid = userModel.validateEmail(email);
                    if (isEmailValid == 0) {     //cek apakah email sudah pernah dipakai sebelumnya
                        String phone = request.getParameter("phone");
                        int isPhoneValid = userModel.validatePhone(phone);
                        if (isPhoneValid == 0) {     //cek apakah phone sudah pernah dipakai sebelumnya
                            //compute md5 hash of password
                            String password = request.getParameter("password");
                            MessageDigest md = MessageDigest.getInstance("MD5");
                            byte[] md5hash = new byte[32];
                            md.update(password.getBytes("iso-8859-1"), 0, password.length());
                            md5hash = md.digest();
                            StringBuffer buf = new StringBuffer();
                            for (int i = 0; i < md5hash.length; i++) {
                                int halfbyte = (md5hash[i] >>> 4) & 0x0F;
                                int two_halfs = 0;
                                do {
                                    if ((0 <= halfbyte) && (halfbyte <= 9)) {
                                        buf.append((char) ('0' + halfbyte));
                                    } else {
                                        buf.append((char) ('a' + (halfbyte - 10)));
                                    }
                                    halfbyte = md5hash[i] & 0x0F;
                                } while (two_halfs++ < 1);
                            }
                            password = buf.toString();
                            //end of computing md5 hash of password

                            String address = request.getParameter("address");
                            
                            String city = request.getParameter("city");
                            int city_id = Integer.parseInt(city);
                            
                            int roleId;
                
                            if (((User) request.getSession().getAttribute("user")).getRoleId() == 1) {
                                roleId = Integer.parseInt(request.getParameter("role"));
                            } else {
                                roleId = ((User) request.getSession().getAttribute("user")).getRoleId();
                            }               
                            
                            int add_id = userModel.signup(username, password, roleId, name, email, address, city_id, phone);
                            if (add_id > 0) {        //add user berhasil, redirect ke halaman manage
                                request.getSession().setAttribute("flash", "Berhasil menambahkan User.");
                            
                                response.sendRedirect("./users?action=manage");
              
                            } else {        //add user gagal
                                request.getSession().setAttribute("flash", "Terjadi masalah dalam proses pengiriman data. Silakan ulangi add users.");
                                request.setAttribute("cities", cities);
                                request.setAttribute("title", "Add Users");
                                request.getRequestDispatcher("users/adduser.jsp").forward(request, response);
                            }
                        } else {        //phone tidak valid (sudah ada di database)
                            request.getSession().setAttribute("flash", "Nomor telepon yang Anda masukkan sudah pernah terdaftar. Silakan lakukan add users dengan nomor telepon lain.");
                            request.setAttribute("cities", cities);
                            request.setAttribute("title", "Add Users");
                            request.getRequestDispatcher("users/adduser.jsp").forward(request, response);
                        }
                    } else {        //email tidak valid (sudah ada di database)
                        request.getSession().setAttribute("flash", "Email yang Anda masukkan sudah pernah terdaftar. Silakan lakukan add users dengan email lain.");
                        request.setAttribute("cities", cities);
                        request.setAttribute("title", "Add Users");
                        request.getRequestDispatcher("users/adduser.jsp").forward(request, response);
                    }
                } else {        //username tidak valid (sudah ada di database)
                    request.getSession().setAttribute("flash", "Username yang Anda masukkan tidak valid karena sudah dipakai oleh user lain. Silakan lakukan add users dengan username lain.");
                    request.setAttribute("cities", cities);
                    request.setAttribute("title", "Add Users");
                    request.getRequestDispatcher("users/adduser.jsp").forward(request, response);
                }
            } else {        //tidak ada masukan pengguna
                request.setAttribute("cities", cities);
                request.setAttribute("roles", roles);
                request.setAttribute("title", "Add Users");
                request.getRequestDispatcher("users/adduser.jsp").forward(request, response);
            }
        } else if (request.getParameter("action").equals("manage")) {
            UserModel userModel = new UserModel();
            ArrayList<User> users = userModel.getAll();
            
            request.setAttribute("users", users);
            request.setAttribute("title", "Manage Users");
            request.getRequestDispatcher("users/manage.jsp").forward(request, response);
        } else if (request.getParameter("action").equals("delete")) {
            if (((User) request.getSession().getAttribute("user")).getRoleId() > 1) {
                response.sendError(403);
            } else {
                int id = Integer.parseInt(request.getParameter("id"));

                UserModel userModel = new UserModel();

                if (userModel.delete(id) == 0) {
                    response.setStatus(404);
                }
            }
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            try {
                processRequest(request, response);
            } catch (SQLException ex) {
                Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            try {
                processRequest(request, response);
            } catch (SQLException ex) {
                Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
